//
//  FPSLabel.swift
//  StarKit
//
//  Created by startimes on 2021/10/13.
//

import UIKit

private let kDefaultSize = CGSize(width: 60, height: 30)

private let fpsUnit = "FPS"
private let fpsFont: UIFont = UIFont.systemFont(ofSize: 14)
private let fpsUnitColor = UIColor.white
private let kScreentWidth = UIScreen.main.bounds.width
private let kScreentHeight = UIScreen.main.bounds.height

public enum FPSFrameType {
    case `super`
    case `self`
    case screen
    
    var `default`: FPSFrameType { return .super }
}

open class FPSLabel: UILabel {
    
    public var frameType: FPSFrameType = .super
    
    private lazy var displayLink: CADisplayLink = {
       let timer = CADisplayLink(target: WeakProxy(self), selector: #selector(tick(sender:)))
        return timer
    }()
   
    private var beforTime = CACurrentMediaTime()
    private var sps_frame: Int = 0
    
    public override init(frame: CGRect) {
        super.init(frame: frame)
        setupUI()
    }
    
    required public init?(coder: NSCoder) {
        super.init(coder: coder)
        setupUI()
    }
    
    private func setupUI() {
        
        layer.cornerRadius = 5
        clipsToBounds = true
        textAlignment = .center
        backgroundColor = UIColor(white: 0, alpha: 0.7)
        
        let fpsString = String(format: "60%@", fpsUnit)
        sps_attributedText(fpsString)
        displayLink.add(to: RunLoop.main, forMode: .common)
    }
    
    open override func layoutSubviews() {
        super.layoutSubviews()
        
        if frameType == .self { return }
        
        frame.size = kDefaultSize
        
        var maxWidth = superview?.frame.width ?? kScreentWidth
        if frameType == .screen {
             maxWidth = kScreentWidth
        }
        
        let x = (maxWidth - frame.size.width) * 0.5
        frame.origin = CGPoint(x: x, y: 20)
    }
    
    @objc func tick(sender: CADisplayLink) {
      
        sps_frame += 1
        let delta = displayLink.timestamp - beforTime
        if delta < 1 { return }
        
        let fps = CFTimeInterval(sps_frame) / delta
        let rateScale: Double = fps / 60.0;
        let fpsString = String(format: "%d%@", Int(round(fps)), fpsUnit)
        
        sps_attributedText(fpsString, rateScale: rateScale)
        
        //重置
        beforTime = displayLink.timestamp
        sps_frame = 0
    }
    
    private func sps_attributedText(_ string: String, rateScale: CGFloat = 1) {
        let fpsLength = string.count
        let fpsAttributeString = NSMutableAttributedString(string: string)
        
        let fpsRange = string.to_cocoaString.range(of: fpsUnit)
        if fpsLength >= fpsRange.length {
            let frameColor = UIColor(hue: 0.27 * (rateScale - 0.2), saturation: 1, brightness: 0.9, alpha: 1)
            fpsAttributeString.addAttribute(NSAttributedString.Key.foregroundColor, value: frameColor, range: NSMakeRange(0, fpsLength - fpsRange.length))
            fpsAttributeString.addAttribute(NSAttributedString.Key.foregroundColor, value: fpsUnitColor, range: fpsRange)
        }
        
        fpsAttributeString.addAttribute(NSAttributedString.Key.font, value: fpsFont, range: NSMakeRange(0, fpsLength))
        attributedText = fpsAttributeString;
    }
    
    deinit {
        displayLink.invalidate()
        print("timer release")
    }
}
